package com.ygp.jmm.ordering;

import org.openjdk.jcstress.annotations.*;
import org.openjdk.jcstress.infra.results.II_Result;


public class TestOrderingTotal {
    /**
     * 案例1: 演示 total ordering 存在的问题
     */
    @JCStressTest
    @Outcome(id = {"1, 0", "0, 1", "1, 1"}, expect = Expect.ACCEPTABLE, desc = "ACCEPTABLE")
    @Outcome(id = "0, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "INTERESTING")
    @State
    public static class Case1 {
        int x;
        int y;

        @Actor
        public void a1(II_Result r) {
            y = 1;
            r.r2 = x;
        }

        @Actor
        public void a2(II_Result r) {
            x = 1;
            r.r1 = y;
        }
    }

    /**
     * 案例2: 演示单个 volatile 变量不能解决 total ordering 的情况
     */
    @JCStressTest
    @Outcome(id = {"1, 0", "0, 1", "1, 1"}, expect = Expect.ACCEPTABLE, desc = "ACCEPTABLE")
    @Outcome(id = "0, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "INTERESTING")
    @State
    public static class Case2 {
        int x;
        volatile int y;

        @Actor
        public void a1(II_Result r) {
            y = 1;
            r.r2 = x;
        }

        @Actor
        public void a2(II_Result r) {
            x = 1;
            r.r1 = y;
        }
    }

    /**
     * 案例3: 演示单个 volatile 变量能解决 total ordering 的情况
     */
    @JCStressTest
    @Outcome(id = {"0, 0", "0, 1", "1, 0"}, expect = Expect.ACCEPTABLE, desc = "ACCEPTABLE")
    @Outcome(id = "1, 1", expect = Expect.FORBIDDEN, desc = "FORBIDDEN")
    @State
    public static class Case3 {
        int x;
        volatile int y;

        @Actor
        public void a1(II_Result r) {
            r.r2 = x;
            y = 1;
        }

        @Actor
        public void a2(II_Result r) {
            r.r1 = y;
            x = 1;
        }
    }

    /**
     * 案例4: 演示两个 volatile 变量可以解决 total ordering 存在的问题
     */
    @JCStressTest
    @Outcome(id = {"1, 0", "0, 1", "1, 1"}, expect = Expect.ACCEPTABLE, desc = "ACCEPTABLE")
    @Outcome(id = "0, 0", expect = Expect.FORBIDDEN, desc = "FORBIDDEN")
    @State
    public static class Case4 {
        volatile int x;
        volatile int y;

        @Actor
        public void a1(II_Result r) {
            y = 1;
            r.r2 = x;
        }

        @Actor
        public void a2(II_Result r) {
            x = 1;
            r.r1 = y;
        }
    }
}
